package com.sdp.wx.handleImpl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.sdp.core.bizc.utils.ApplicationContextUtils;
import com.sdp.core.bizc.vo.BusinessContext;
import com.sdp.wx.controller.WxRepairCodeController;
import com.sdp.wx.db.wx_repair_vehicle_wz.entity.WxRepairVehicleWz;
import com.sdp.wx.db.wx_repair_vehicle_wz.service.IWxRepairVehicleWzService;
import com.sdp.wx.db.wx_warehouse_info.entity.WxWarehouseInfo;
import com.sdp.wx.db.wx_warehouse_info.service.IWxWarehouseInfoService;
import com.sdp.wx.db.wx_warehouse_right.service.IWxWarehouseRightService;
import com.sdp.wx.db.wx_wz_input.entity.WxWzInput;
import com.sdp.wx.db.wx_wz_input.service.IWxWzInputService;
import com.sdp.wx.db.wx_wz_input_detail.entity.WxWzInputDetail;
import com.sdp.wx.db.wx_wz_input_detail.service.IWxWzInputDetailService;
import com.sdp.wx.db.wx_wz_now_num.entity.WxWzNowNum;
import com.sdp.wx.db.wx_wz_now_num.service.IWxWzNowNumService;
import com.sdp.wx.db.wx_wz_output.entity.WxWzOutput;
import com.sdp.wx.db.wx_wz_output.service.IWxWzOutputService;
import com.sdp.wx.db.wx_wz_output_detail.entity.WxWzOutputDetail;
import com.sdp.wx.db.wx_wz_output_detail.service.IWxWzOutputDetailService;
import com.sdp.wx.handle.WzInOutPutHandle;
import com.sdp.wx.utils.CurrentLoginEmp;
import com.sdp.wx.utils.WxConstants;
import com.sdp.wx.view.WxWzInputView;

import cn.hutool.core.bean.BeanUtil;

@Component
public class WzRepairOutPutHandleImpl extends WzInOutPutHandle{
	
	@Autowired
	private CurrentLoginEmp currentLoginEmp;
	
	@Autowired
	private IWxWarehouseInfoService iWxWarehouseInfoService;
	
	@Autowired
	private IWxWarehouseRightService iWxWarehouseRightService;
	
	@Autowired
	private IWxWzNowNumService iWxWzNowNumService;
	
	@Autowired
	private IWxWzInputDetailService iWxWzInputDetailService;
	
	@Autowired
	private IWxWzInputService iWxWzInputService;
	
	@Autowired
	private WxRepairCodeController wxRepairCodeController;
	
	@Autowired
	private IWxWzOutputService iWxWzOutputService;
	
	@Autowired
	private IWxWzOutputDetailService iWxWzOutputDetailService;
	
	@Autowired
	private IWxRepairVehicleWzService iWxRepairVehicleWzService;

	@Override
	public BusinessContext execute(BusinessContext businessContext) {
		return ApplicationContextUtils.getBean(WzRepairOutPutHandleImpl.class).wzRepairOutput(businessContext);
	}
	
	@Transactional(rollbackFor=Exception.class)
	public BusinessContext wzRepairOutput(BusinessContext businessContext) {
		JSONObject emp = currentLoginEmp.getCurrentLoginInfo();
		if(StringUtils.isEmpty(emp)) {
			businessContext.setMessage("请先登录系统");
			businessContext.setSuccess(false);
			return businessContext;
		}
		
		List<WxRepairVehicleWz> wzList = businessContext.get(WxRepairVehicleWz.class);
		WxWzOutput output = businessContext.get(WxWzOutput.class);
		if(output==null || wzList==null || wzList.size()==0) {
			businessContext.setSuccess(false);
			businessContext.setMessage("领料信息为空，不能出库");
			return businessContext;
		}
		
		//判断仓库是否锁定
		WxWarehouseInfo warehouseInfo = iWxWarehouseInfoService.queryWxWarehouseInfoByCode(output.getWarehouseCode());
		if(warehouseInfo==null || WxConstants.是.getCode().equals(warehouseInfo.getIsLock())) {
			businessContext.setMessage("仓库目前处于盘存状态，无法进行出库");
			businessContext.setSuccess(false);
			return businessContext;
		}
		
		//判断当前操作人是否有领料出库的权限
		boolean haveRight = iWxWarehouseRightService.isHaveRight(emp.getString("empNo"), output.getWarehouseCode(),WxConstants.库管权限_领料出库.getCode());
		if(!haveRight) {
			businessContext.setMessage("您没有此仓库的领料出库权限");
			businessContext.setSuccess(false);
			return businessContext;
		}
		
		
		
		Map<String,BigDecimal> outputNumMap = new HashMap<>();
		Map<String,BigDecimal> backUpOutputNumMap = new HashMap<>();
		Set<String> wzNos = new HashSet<String>();
		for(WxRepairVehicleWz wz : wzList) {
			
			wzNos.add(wz.getWzNo());
			if(outputNumMap.containsKey(wz.getWzNo())) {
				outputNumMap.put(wz.getWzNo(), wz.getNotOutputNum().add(outputNumMap.get(wz.getWzNo())));
			}else {
				outputNumMap.put(wz.getWzNo(), wz.getNotOutputNum());
			}
			
			//已出库数量= 已出库数量+本次出库数量（）
			wz.setOutputNum(wz.getOutputNum().add(wz.getNotOutputNum()));
			
			//未出库数量 = 领料数-已出库数
			wz.setNotOutputNum(wz.getPickNum().subtract(wz.getOutputNum()));
		}
		//备份一下，后面更新库存时候需要用到
		BeanUtil.copyProperties(outputNumMap, backUpOutputNumMap);
		
		//先检查下物资库存是否满足
		List<String> wzNoList = new ArrayList<String>(wzNos);
		List<WxWzNowNum> wzNowNumList = iWxWzNowNumService.queryWzNowNumByWzCodes(wzNoList, output.getWarehouseCode());
		if(wzNowNumList==null || wzNowNumList.size()==0) {
			businessContext.setSuccess(false);
			businessContext.setMessage("库存信息为空，无法验证库存，不能出库！");
			return businessContext;
		}
		if(wzNoList.size()!=wzNowNumList.size()) {
			businessContext.setSuccess(false);
			businessContext.setMessage("有器材无法在库存信息中检索到，无法验证库存，不能出库！");
			return businessContext;
		}
		
		//检测出库数量是否有大于库存的，如果有大于库存的，将
		for(WxWzNowNum wz : wzNowNumList) {
			if(outputNumMap.containsKey(wz.getWzNo())) {
				if(outputNumMap.get(wz.getWzNo()).compareTo(wz.getNowNum())>0) {
					businessContext.setSuccess(false);
					businessContext.setMessage("器材编码《"+wz.getWzNo()+"》出库数量:"+outputNumMap.get(wz.getWzNo())+"大于库存数量:"+wz.getNowNum()+"，不能出库！");
					break;
				}
			}
		}
		
		if(!businessContext.isSuccess()) {
			return businessContext;
		}
		
		LocalDateTime now = LocalDateTime.now();
		
		//要修改的入库单信息
		List<WxWzInputDetail> wzInputDetailList = new ArrayList<>();
		//需要修改的入库单主表的编号map
		Map<String, String> wzInputCodeMap = new HashMap<>();
		
		List<WxWzOutputDetail> wzOutputDetailList = new ArrayList<>();
				
		QueryWrapper<WxWzInputView> queryWrapper = new QueryWrapper<>();
		queryWrapper.in("b.wz_no", wzNoList);
		queryWrapper.orderByAsc("a.input_time");
		iWxWzInputDetailService.queryInputInfo(queryWrapper, new ResultHandler<WxWzInputView>() {
			WxWzInputView inputView = null;
			WxWzInputDetail wzInputDetail = null;
			WxWzOutputDetail wzOutputDetail = null;
			@Override
			public void handleResult(ResultContext<? extends WxWzInputView> resultContext) {
				if(outputNumMap.size()==0) {
					resultContext.stop();
				}
				inputView = resultContext.getResultObject();
				if(outputNumMap.containsKey(inputView.getWzNo())) {
					wzInputDetail = new WxWzInputDetail();
					
					if(outputNumMap.get(inputView.getWzNo()).compareTo(BigDecimal.ZERO)>0) {
						//如果还没出完
						//生成出库信息
						wzOutputDetail = new WxWzOutputDetail();
						BeanUtil.copyProperties(inputView, wzOutputDetail);
						wzOutputDetail.setInputDetailId(inputView.getKeyId());
						wzOutputDetail.setCreateTime(now);
						wzOutputDetail.setKeyId(null);
						if(outputNumMap.get(inputView.getWzNo()).compareTo(inputView.getNowNum())>0) {
							//如果说，出库数量大于这条记录的当前库存
							wzOutputDetail.setOutputNum(inputView.getNowNum());
							
							//将出库数量减去当前库存
							outputNumMap.put(inputView.getWzNo(), outputNumMap.get(inputView.getWzNo()).subtract(inputView.getNowNum()));
						
							//将当前库存数量变为0
							BeanUtil.copyProperties(inputView, wzInputDetail);
							wzInputDetail.setNowNum(BigDecimal.ZERO);
							wzInputDetailList.add(wzInputDetail);
							//添加待修改的入库单编号
							wzInputCodeMap.put(wzInputDetail.getInputCode(), wzInputDetail.getInputCode());
						}else {
							//出库数量小于当前库存
							//设置 出库数量
							wzOutputDetail.setOutputNum(outputNumMap.get(inputView.getWzNo()));

							//修改当前库存
							BeanUtil.copyProperties(inputView, wzInputDetail);
							wzInputDetail.setNowNum(inputView.getNowNum().subtract(outputNumMap.get(inputView.getWzNo())));
							wzInputDetailList.add(wzInputDetail);
							//添加待修改的入库单编号
							wzInputCodeMap.put(wzInputDetail.getInputCode(), wzInputDetail.getInputCode());

							//将出库数量变为0
							outputNumMap.put(inputView.getWzNo(), BigDecimal.ZERO);
							//将出完的物资删除
							outputNumMap.remove(inputView.getWzNo());
						}
						
						wzOutputDetailList.add(wzOutputDetail);
					}
				}
	
			}
			
		});
		
		if(wzOutputDetailList.size()>0) {
			output.setKeyId(null);
			output.setOutputDate(LocalDate.now());
			output.setOutputTime(now);
			output.setCreateTime(now);
			output.setIsUse(WxConstants.是.getCode());
			output.setOpName(emp.getString("empName"));
			output.setOpNo(emp.getString("empNo"));
			output.setOutputType(WxConstants.出库类型_领料出库.getCode());
			output.setOutputCode(wxRepairCodeController.getCode(WxConstants.流水号前缀_器材出库单.getCode(), WxConstants.流水号类型_器材出库单.getCode()));
			BigDecimal outputAmount = BigDecimal.ZERO;
			BigDecimal armyAmount = BigDecimal.ZERO;
			BigDecimal saleAmount = BigDecimal.ZERO;
			for(WxWzOutputDetail wz : wzOutputDetailList) {
				wz.setOutputCode(output.getOutputCode());
				wz.setRepairCode(output.getRepairCode());
				outputAmount = outputAmount.add(wz.getPurchasePrice().multiply(wz.getOutputNum()).setScale(2, BigDecimal.ROUND_HALF_UP));
				armyAmount = armyAmount.add(wz.getArmyPrice().multiply(wz.getOutputNum()).setScale(2, BigDecimal.ROUND_HALF_UP));
				saleAmount = saleAmount.add(wz.getSalePrice().multiply(wz.getOutputNum()).setScale(2, BigDecimal.ROUND_HALF_UP));
			}
			
			output.setOutputAmount(outputAmount);
			output.setArmyAmount(armyAmount);
			output.setSaleAmount(saleAmount);
			
			if(wzInputDetailList.size()>0) {
				iWxWzInputDetailService.updateBatchById(wzInputDetailList);
				//更新入库单的是否出库字段
				UpdateWrapper<WxWzInput> updateWrapper = new UpdateWrapper<>();
				updateWrapper.lambda().in(WxWzInput::getInputCode, new ArrayList<String>(wzInputCodeMap.values()))
					.set(WxWzInput::getIsOutput, WxConstants.是.getCode());
				iWxWzInputService.update(updateWrapper);
			}
			
			iWxWzOutputService.save(output);
			iWxWzOutputDetailService.saveBatch(wzOutputDetailList);
			
			iWxRepairVehicleWzService.updateBatchById(wzList);
			
			//更新库存
			iWxWzNowNumService.wzNowNumSubtract(wzNoList, backUpOutputNumMap, output.getWarehouseCode());
		}

		return businessContext;
	}

}
